package service.classify
{
    import mx.controls.Alert;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.remoting.mxml.RemoteObject;

    import common.Config;
    import model.classify.ClassifyTableList;
    import model.classify.ClassifyResult;
    import model.classify.ClassifyAttributeList;

    public class ClassifyService
    {
        [Bindable]
        public var classifyTableList:ClassifyTableList;
        [Bindable]
        public var classifyResult:ClassifyResult;
        [Bindable]
        public var classifyAttributeList:ClassifyAttributeList;

        private var remoteObject:RemoteObject;
        private static var _instance:ClassifyService;

        public function ClassifyService(privateClass:PrivateClass)
        {
            this.remoteObject = new RemoteObject();
            this.remoteObject.destination = "ClassifyGateway"
            this.remoteObject.endpoint = Config.serverUrl;
            this.remoteObject.requestTimeout = Config.requestTimeout;
            this.remoteObject.concurrency = Config.concurrency;
            this.remoteObject.showBusyCursor = true;

            this.classifyTableList = new ClassifyTableList();
            this.classifyResult = new ClassifyResult();
            this.classifyAttributeList = new ClassifyAttributeList();
        }

        public static function getInstance():ClassifyService
        {
            if(ClassifyService._instance == null)
            {
                ClassifyService._instance = new ClassifyService(
                                                new PrivateClass());
            }
            return ClassifyService._instance;
        }

        public function addListeners(resultFunc:Function,
                                     faultFunc:Function):void
        {
            this.remoteObject.addEventListener(ResultEvent.RESULT,
                                               resultFunc);
            this.remoteObject.addEventListener(FaultEvent.FAULT,
                                               faultFunc);
        }

        public function removeListeners(resultFunc:Function,
                                        faultFunc:Function):void
        {
            this.remoteObject.removeEventListener(ResultEvent.RESULT,
                                                  resultFunc);
            this.remoteObject.removeEventListener(FaultEvent.FAULT,
                                                  faultFunc);
        }

        //--------------------------------------------------------------------
        // TODO: get all data table
        public function getTableList():void
        {
            this.addListeners(getTableListResult, getTableListFault);
            this.remoteObject.getTableList();
        }

        public function getTableListResult(event:ResultEvent):void
        {
            this.removeListeners(getTableListResult, getTableListFault);
            this.classifyTableList.update(event.message.body.tableList);

        }

        public function getTableListFault(event:FaultEvent):void
        {
            this.removeListeners(getTableListResult, getTableListFault);
            Alert.show("Get data table fault");
        }
        
        //--------------------------------------------------------------------
        //TODO: get attribute list of a table

        public function getAttributeList(table:String):void
        {
            this.addListeners(getAttributeListResult, getAttributeListFault);
            this.remoteObject.getAttributeList(table);
        }

        public function getAttributeListResult(event:ResultEvent):void
        {
            this.removeListeners(getAttributeListResult, getAttributeListFault);
            this.classifyAttributeList.update(event.message.body.attributeList);
        }

        public function getAttributeListFault(event:FaultEvent):void
        {
            this.removeListeners(getAttributeListResult, getAttributeListFault);
            Alert.show("Get Attribute List Fault");
        }

        //--------------------------------------------------------------------
        //TODO: c45Classify
        public function c45Classify(attribute:String, accuracy:Number, attribute_list:Array):void
        {
            this.addListeners(c45ClassifyResult, c45ClassifyFault);

            this.remoteObject.c45Classify(attribute, accuracy, attribute_list);
        }

        public function c45ClassifyResult(event:ResultEvent):void
        {
            this.removeListeners(c45ClassifyResult, c45ClassifyFault);
            this.classifyResult.update(event.message.body.result);
        }

        public function c45ClassifyFault(event:FaultEvent):void
        {
            this.removeListeners(c45ClassifyResult, c45ClassifyFault);
            Alert.show("C45 classify fault");
        }

        //---------------------------------------------------------------------
        //TODO: discretize attribute
        public function discretizeAttribute(attribute:String, granularity:Number):void
        {
            this.addListeners(discretizeAttributeResult, discretizeAttributeFault);
            this.remoteObject.discretizeAttribute(attribute, granularity);
        }
        
        public function discretizeAttributeResult(event:ResultEvent):void
        {
            this.removeListeners(discretizeAttributeResult, discretizeAttributeFault);
        }

        public function discretizeAttributeFault(event:FaultEvent):void
        {
            this.removeListeners(discretizeAttributeResult, discretizeAttributeFault);
            Alert.show("discretize attribute fault");
        }
    }
}

class PrivateClass
{
    public function PrivateClass() {}
}
